package conf

import (
	"encoding/json"
	"errors"
	"os"
	"sync"

	"github.com/BurntSushi/toml"
	"github.com/zxysilent/logs"
	"github.com/zxysilent/utils"
)

type appconf struct {
	Title      string `toml:"title"`
	Intro      string `toml:"intro"`
	UdpPort    int    `toml:"upd_port"`
	HttpPort   int    `toml:"http_port"`
	HttpSrv    string `toml:"http_srv"`
	RootDir    string `toml:"root_dir"`
	FileExt    string `toml:"file_ext"`
	BufSize    int    `toml:"buf_size"` //KB
	SplitSync  int64  `toml:"split_sync"`
	SplitFile  int64  `toml:"split_file"`  //MB
	SaveUnknow bool   `toml:"save_unknow"` //MB
}

var (
	App       *appconf
	defConfig = "./conf/conf.toml"
	defIpctn  = "./conf/ipctn.json"
)

func (app *appconf) DefDir() string {
	return app.RootDir + "/run"
}
func Init() {
	var err error
	App, err = initConf()
	if err != nil {
		logs.Fatal("config init error : ", err.Error())
	}
	App.BufSize *= 1024
	App.SplitFile *= 1024 * 1024
	logs.Debug("conf init")
}

func initConf() (*appconf, error) {
	app := &appconf{}
	_, err := toml.DecodeFile(defConfig, &app)
	if err != nil {
		return nil, err
	}
	return app, nil
}

// Ipitem ip 地址
type Ipitem struct {
	Guid string `json:"guid"`
	Addr string `json:"addr"`
	Note string `json:"note"`
}

type ipctn struct {
	sets []Ipitem
	lock sync.Mutex
}

func NewIpctn() *ipctn {
	//instance
	inst := new(ipctn)
	inst.Load()
	return inst
}

// Load 加载
func (ipc *ipctn) Load() error {
	ipc.lock.Lock()
	defer ipc.lock.Unlock()
	fin, err := os.Open(defIpctn)
	if err != nil {
		return nil
	}
	defer fin.Close()
	return json.NewDecoder(fin).Decode(&ipc.sets)
}

// Store 存储
func (ipc *ipctn) Store() error {
	ipc.lock.Lock()
	defer ipc.lock.Unlock()
	fin, err := os.Create(defIpctn)
	if err != nil {
		return nil
	}
	defer fin.Close()
	return json.NewEncoder(fin).Encode(ipc)
}

// Add 添加项
func (ipc *ipctn) Add(item Ipitem) error {
	ipc.lock.Lock()
	defer ipc.lock.Unlock()
	item.Guid = utils.RandStr(10)
	ipc.sets = append(ipc.sets, item)
	return nil
}

// All 所有
func (ipc *ipctn) All() []Ipitem {
	ipc.lock.Lock()
	defer ipc.lock.Unlock()
	return ipc.sets
}

// AllIp 所有Ip
func (ipc *ipctn) AllIp() []string {
	ipc.lock.Lock()
	defer ipc.lock.Unlock()
	ips := make([]string, 0, len(ipc.sets))
	for _, val := range ipc.sets {
		ips = append(ips, val.Addr)
	}
	return ips
}

// Set 修改项
func (ipc *ipctn) Set(item Ipitem) error {
	ipc.lock.Lock()
	defer ipc.lock.Unlock()
	for idx := range ipc.sets {
		if ipc.sets[idx].Guid == item.Guid {
			ipc.sets[idx].Addr = item.Addr
			ipc.sets[idx].Note = item.Note
			return nil
		}
	}
	return errors.New("item not found")
}

// Drop 删除项
func (ipc *ipctn) Drop(item Ipitem) error {
	ipc.lock.Lock()
	defer ipc.lock.Unlock()
	gidx := -1
	for idx := range ipc.sets {
		if ipc.sets[idx].Guid == item.Guid {
			gidx = idx
		}
	}
	if gidx == -1 {
		return errors.New("item not found")
	}
	// 将删除点前后的元素连接起来
	ipc.sets = append(ipc.sets[:gidx], ipc.sets[gidx+1:]...)
	return nil
}
